#include "widget_topo_graph.h"
#include "com_rs232.h"
#include "topo_info.h"
#include "ui_widget_topo_graph.h"
#include "example_nodes.h"

#include <com_manager.h>
#include "topo_info.h"

#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif


WidgetTopoGraph::WidgetTopoGraph(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::WidgetTopoGraph)
    , scene(nullptr)
{
    ui->setupUi(this);


    //createActions();
   // createMenus();

    scene = new ExampleDiagramScene(itemMenu);
    //dw ugly
    scene->mItemMenu = itemMenu;
    this->scene->mode = 0;

    int width =  1800;
    int height = 800;
    scene->setSceneRect(QRectF(0, 0, width, height));
    //dw
    connect(scene, SIGNAL(nodeItemInserted(NodeItem*)),
            this, SLOT(itemInserted(NodeItem*)));

    QHBoxLayout *layout = new QHBoxLayout;
    //dw new5
    view = new QGraphicsView(scene);

    view->centerOn(0, height/3);

    //view = new MyFasterGraphicView(scene);
    view->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);

    layout->addWidget(view);

    //QWidget *widget = new QWidget;
    setLayout(layout);

  //  setCentralWidget(widget);
    setWindowTitle(tr("NodeEditorScene"));

   //  scene->setBackgroundBrush(QPixmap(":/images/background3.png"));

    update_chart();


  //   scene-> setFocusItem(gui_node_map.last() );




}

WidgetTopoGraph::~WidgetTopoGraph()
{
    delete ui;
}

void WidgetTopoGraph::deleteItem()
{
    if (scene->selectedItems().count()) {
        foreach (QGraphicsItem *item, scene->selectedItems()) {
            /*//now in dtor:
            if (item->type() == DiagramItem::Type) {
                qgraphicsitem_cast<DiagramItem *>(item)->removeArrows();
            }

            //dw isn't it better to delete stuff in destructors??
            if (item->type() == NodeItem::Type) {
                qgraphicsitem_cast<NodeItem *>(item)->removeConnections();
            }
            */

            //dw we are doing that now in removeConnections from idem dtor, is that good idea?
            //scene->removeItem(item);

            //can we delete all item or better only ours, and why is it not deleted automatically on removal? what is the correct way?
            delete item;
        }
        scene->clearSelection();
        scene->clearFocus();
    }
    //maybe we are embedding a window so handle this too (TODO: is there a better way?)
    else if (this->scene->focusItem() && this->scene->focusItem()->type() == NodeItem::Type) {
        NodeItem* item = qgraphicsitem_cast<NodeItem *>(this->scene->focusItem());
        //now in dtor: item->removeConnections();

        //dw we are doing that now in removeConnections from idem dtor, is that good idea?
        //scene->removeItem(item);
        delete item;
        scene->clearSelection();
        scene->clearFocus();
    }

}


void WidgetTopoGraph::on_node_changed()
{
    QList<int> list = TopoInfo::Instance()->node_map.keys();




    update_chart();

    scene->clearSelection();
    scene->clearFocus();
    scene->update();


}
void  WidgetTopoGraph::update_chart()
{
    int width =  1000;
    int height = 800;

    QMap<int, TOPO_NODE *>::Iterator  it = TopoInfo::Instance()->node_map.begin();
    // int cnt =  TopoSetting::node_map.count();
    int x =   width / 4 ;
    int y = height/4;

    QMap<int, ExampleBaseNode*> gui_old;
      gui_node_map.swap(gui_old);

    gui_node_map.clear();
    while  (it != TopoInfo::Instance()-> node_map.end())
    {
        TOPO_NODE * net_node = it.value();
        ExampleBaseNode *gui_node;
        if ( gui_old.contains(it.key()))
        {
            gui_node = gui_old[it.key()];
            gui_old.remove(it.key());
        }
        else
        {
            gui_node = (ExampleBaseNode*)   scene-> createNode(8);
            gui_node ->setPos( x ,  y );

            foreach( TOPO_PHY * phy, net_node->phy)
            {
                if (phy !=nullptr )
                {
                    gui_node ->addConnectorAndLabel(QString("PHY%1").arg(phy->_phy), NodeConnector::InOut, NodeConnector::Bottom);
                }
            }

            gui_node ->addConnectorAndLabel(QString("Node: %1").arg(net_node->_id), NodeConnector::InOut, NodeConnector::Top);
            gui_node->update();
            x += 250;
            if ( x  > width * 3/ 4)
            {
                x = width / 4 ;
                y += 160;
            }
        }
         gui_node_map[it.key() ] = gui_node ;






        it++;
    }


    QList< TOPO_NODE *> node_list=  TopoInfo::Instance()->node_map.values();
    for (int i =0; i <  node_list.count(); i++ )
    {
        TOPO_NODE * node = node_list[i];
        if ( node == nullptr)
            continue;
        int id_1 =node->_id;
        if(  gui_node_map.contains(id_1))
        {
            ExampleBaseNode *node_1 =  gui_node_map[id_1];
            node_1->connectors[0] ->deleteConnections();
        }
    }

    //QList< TOPO_NODE *> node_list=  TopoInfo::Instance()->node_map.values();
    for (int i =0; i <  node_list.count(); i++ )
    {
        TOPO_NODE * node = node_list[i];
        if ( node == nullptr)
            continue;
        if (node->phy.isEmpty() )
            continue;

        TOPO_PHY * phy = node->phy.first() ;
        if ( phy == nullptr || phy->target == NULL)
            continue;
        int id_1 =node->_id;// i%node_list.count();

        //TODO: fix
        int id_2 = phy->target->_node ;


        if ( gui_node_map.contains(id_1) && gui_node_map.contains(id_2))
        {
            ExampleBaseNode *node_1 =  gui_node_map[id_1];
            ExampleBaseNode *node_2 = gui_node_map[id_2];

            if ( node_1 != nullptr)
                node_1->updateConnectorsPos();
            if ( node_2 != nullptr)
                node_2->updateConnectorsPos();

            if ( node_1 != nullptr && node_2 != nullptr)
            {
                NodeConnector* thisCon = node_1->connectors[ phy->_phy ];
                NodeConnector* oCon = node_2->connectors[phy->target->_phy ];
                NodeConnection *  newCon = new NodeConnection(oCon, thisCon, NULL, scene );

                thisCon->addConnection(newCon);
                oCon->addConnection(newCon);

            }
        }
    }
    QFile file(":/qss/dw3.qss");
    file.open(QFile::ReadOnly);
    QString styleSheet = QLatin1String(file.readAll());
    // currentStylesheet = stylesheetName;
    foreach( QGraphicsItem* i, scene->items()) {
        //if (i->inherits("ExampleBaseNode")) {
        if (i->type() == NodeItem::Type) {
            ExampleBaseNode* n = static_cast<ExampleBaseNode*>(i);
            n->widget()->setStyleSheet(styleSheet);
        //    n->update();
        }
    }


    QMap<int, ExampleBaseNode*> ::Iterator it_old = gui_old.begin();
    while( it_old!=gui_old.end() )
    {
        scene->removeItem( *it_old);
        delete *it_old;

        it_old++;
    }

    view->invalidateScene(QRectF(0, 0, width, height) );
}

//! [24]
void WidgetTopoGraph::createMenus()
{

    itemMenu =new QMenu(tr("&Item"),this); // addMenu(tr("&Item"));
    itemMenu->addAction(deleteAction);
    itemMenu->addSeparator();
    itemMenu->addAction(toFrontAction);
    itemMenu->addAction(sendBackAction);

    /*
    //FIXME: cleanup and release memory!
    StyleSheetEditor* styleSheetEditor = new StyleSheetEditor(this);
    QMenu* qssMenu = menuBar()->addMenu(tr("&Style"));
    QAction* styleAction = new QAction(QIcon(":/images/bringtofront.png"),
                                tr("Edit &Style"), this);
    styleAction->setShortcut(tr("Ctrl+Y"));
    styleAction->setStatusTip(tr("Edit Style"));
    qssMenu->addAction(styleAction);
    connect(styleAction, SIGNAL(triggered()),
            styleSheetEditor, SLOT(show()));
    connect(styleSheetEditor, SIGNAL(newStyle(const QString&)),
            this, SLOT(setNodeItemsStyle(const QString&)));
    connect(styleSheetEditor, SIGNAL(newStylesheet(const QString&)),
            this, SLOT(setNodeItemsStylesheet(const QString&)));

    //FIXME: cleanup and release memory!
    WindowFlagsEditor* windowFlagsEditor = new WindowFlagsEditor(this);
    QMenu* flagsMenu = menuBar()->addMenu(tr("&WindowFlags"));
    QAction* flagsAction = new QAction(QIcon(":/images/bringtofront.png"),
                                tr("Edit &Style"), this);
    flagsAction->setShortcut(tr("Ctrl+F"));
    flagsAction->setStatusTip(tr("Edit WindowFlags"));
    flagsMenu->addAction(flagsAction);
    connect(flagsAction, SIGNAL(triggered()),
            windowFlagsEditor, SLOT(show()));
    connect(windowFlagsEditor, SIGNAL(newWindowFlags(Qt::WindowFlags)),
            this, SLOT(setNoteItemsWindowFlags(Qt::WindowFlags)));
            */


    // aboutMenu = menuBar()->addMenu(tr("&Help"));
    // aboutMenu->addAction(aboutAction);
}


//! [23]
void WidgetTopoGraph::createActions()
{
    toFrontAction = new QAction(QIcon(":/images/bringtofront.png"),
                                tr("Bring to &Front"), this);
    toFrontAction->setShortcut(tr("Ctrl+F"));
    toFrontAction->setStatusTip(tr("Bring item to front"));
    connect(toFrontAction, SIGNAL(triggered()),
            this, SLOT(bringToFront()));
    //! [23]

    sendBackAction = new QAction(QIcon(":/images/sendtoback.png"),
                                 tr("Send to &Back"), this);
    sendBackAction->setShortcut(tr("Ctrl+B"));
    sendBackAction->setStatusTip(tr("Send item to back"));
    connect(sendBackAction, SIGNAL(triggered()),
            this, SLOT(sendToBack()));

    deleteAction = new QAction(QIcon(":/images/delete.png"),
                               tr("&Delete"), this);
    deleteAction->setShortcut(tr("Delete"));
    deleteAction->setStatusTip(tr("Delete item from diagram"));
    connect(deleteAction, SIGNAL(triggered()),
            this, SLOT(deleteItem()));


}


void WidgetTopoGraph::contextMenuEvent(QContextMenuEvent *event)
{
}
